#include "Channel.h"
#include <poll.h>

#include "EventLoop.h"
#include "PlatLogger.h"
#include "Poller.h"

namespace xncc {
namespace foundation {
    static constexpr int kNoneEvent  = 0;
    static constexpr int kReadEvent  = POLLIN | POLLPRI;
    static constexpr int kWriteEvent = POLLOUT;

    Channel::Channel(EventLoop* loop, int sockfd, types::connection_id_t connId)
        : loop_(loop), fd_(sockfd), connId_(connId)
    {
    }

    Channel::~Channel() = default;

    void Channel::init()
    {
        // 跨线程调用，epoll_ctl是线程安全的
        loop_->poller()->addChannel(shared_from_this());
    }

    void Channel::update() { loop_->poller()->updateChannel(shared_from_this()); }

    void Channel::remove() { loop_->poller()->removeChannel(shared_from_this()); }

    void Channel::enableReading()
    {
        events_ |= kReadEvent;
        update();
    }
    void Channel::disableReading()
    {
        events_ &= ~kReadEvent;
        update();
    }
    void Channel::enableWriting()
    {
        events_ |= kWriteEvent;
        update();
    }
    void Channel::disableWriting()
    {
        events_ &= ~kWriteEvent;
        update();
    }
    void Channel::disableAll()
    {
        events_ = kNoneEvent;
        update();
    }
    bool Channel::isNoneEvent() const { return events_ == kNoneEvent; }

    bool Channel::isWriting() const { return (events_ & kWriteEvent) != 0; }
    bool Channel::isReading() const { return (events_ & kReadEvent) != 0; }

    void Channel::handleClose(const std::string& reason)
    {
        if (closeCallback_) {
            closeCallback_(reason);
        }
        else {
            TRACE_ERROR << "closeCallback_ func not init, channel fd = "_s << fd_ << " connid:" << connId_;
        }
    }
    void Channel::handleRead()
    {
        if (readCallback_) {
            readCallback_();
        }
        else {
            TRACE_ERROR << "readCallback_ func not init connid:"_s << connId_;
        }
    }
    void Channel::handleWrite()
    {
        if (writeCallback_) {
            writeCallback_();
        }
        else {
            TRACE_ERROR << "writeCallback_ func not init connid:"_s << connId_;
        }
    }
    void Channel::handleError(const std::string& reason)
    {
        if (errorCallback_) {
            errorCallback_(reason);
        }
        else {
            TRACE_ERROR << "errorCallback_ func not init call handle close connid: "_s << connId_;
            handleClose(reason);
        }
    }

    auto Channel::loopId() const -> types::thread_id_t { return loop_->id(); }

    void Channel::RunTask(types::Task func) { loop_->runInLoop(std::move(func)); }

    auto Channel::loopType() const -> types::IO_MULTI_MODE::value { return loop_->mode(); }

    auto Channel::UserFuncs() const -> const std::map<types::message_id_t, types::UserFunc>&
    {
        return loop_->getUserFuncs();
    }

}  // namespace foundation
}  // namespace xncc